import numpy as np
import math

import win32con
import win32gui


def get_screen_position(other_x, other_y, other_z, screen_width, screen_height, transformation_array):

    x_offset = screen_width / 2
    y_offset = screen_height / 2

    np.set_printoptions(precision=3, suppress=True)

    transformation_array = np.array(transformation_array)

    # --- 直接用numpy矩阵乘法
    # other_xyz = np.array([other_x, other_y, other_z, 1]).reshape(1, -1)
    # new_other_xyz = (other_xyz @ transformation_array.T)
    # other_xyz.shape, transformation_array.T.shape
    # new_other_xyz = new_other_xyz.reshape(-1, )
    # new_other_z = new_other_xyz[2]
    # if new_other_z <= 0:
    #     return 0, (0, 0, 0, 0)
    #
    # depth = 1 / new_other_z

    # --- 手算
    x1 = other_x * transformation_array[0][0] + other_y * transformation_array[0][1] + other_z * transformation_array[0][2] + transformation_array[0][3]
    y1 = other_x * transformation_array[1][0] + other_y * transformation_array[1][1] + other_z * transformation_array[1][2] + transformation_array[1][3]
    z1 = other_x * transformation_array[2][0] + other_y * transformation_array[2][1] + other_z * transformation_array[2][2] + transformation_array[2][3]
    y2 = other_x * transformation_array[1][0] + other_y * transformation_array[1][1] + (other_z + 70) * transformation_array[1][2] + transformation_array[1][3]

    if z1 <= 0:
        return 0, (0, 0, 0, 0)

    depth = 1 / z1

    # print("new_xyz:", np.round([x1, y1, z1], 3), f'--- y2: {y2: .3f}')

    screen_x = x_offset + x1 * depth * x_offset
    screen_y1 = y_offset - y2 * depth * y_offset
    screen_y2 = y_offset - y1 * depth * y_offset  # 这里要反转y1和y2
    height_y12 = screen_y2 - screen_y1
    width_x12 = height_y12 * 0.5

    # print("[screen_x, screen_y1, screen_y2]:", np.round([screen_x, screen_y1, screen_y2], 3), f'--- height_y12 {height_y12: .3f}')

    rect_pos = [int(v) for v in (screen_x - width_x12 / 2, screen_y1, screen_x + width_x12 / 2, screen_y2)]
    return 1, rect_pos


def clamp_rect_to_window(rect, win_rect):
    """
    rect     : (x0, y0, x1, y1)  原始矩形（逻辑坐标）
    win_rect : (left, top, right, bottom)  窗口矩形（屏幕坐标）
    return   : (x0', y0', x1', y1')  限制后的矩形，保证完全落在窗口内
    """
    w_left, w_top, w_right, w_bottom = win_rect
    x0, y0, x1, y1 = rect

    # 1. 平移到窗口内（加上窗口左上角偏移）
    x0 += w_left
    y0 += w_top
    x1 += w_left
    y1 += w_top

    # 2. 硬卡边界
    x0 = max(w_left,   min(x0, w_right))
    y0 = max(w_top,    min(y0, w_bottom))
    x1 = max(w_left,   min(x1, w_right))
    y1 = max(w_top,    min(y1, w_bottom))

    # 3. 如果卡完后顺序反了，交换一下保证 x0<=x1, y0<=y1
    if x0 > x1:
        x0, x1 = x1, x0
    if y0 > y1:
        y0, y1 = y1, y0

    return [x0, y0, x1, y1]


def draw_rect_by_position(dc, cdc, x0, y0, x1, y1, size, brush):
    """
    通过左上角和右下角坐标绘制矩形边框
    :param dc: 设备上下文
    :param cdc: 兼容设备上下文
    :param x0: 左上角x坐标
    :param y0: 左上角y坐标
    :param x1: 右下角x坐标
    :param y1: 右下角y坐标
    :param size: 边框宽度
    :param brush: 填充画刷
    """
    # 计算矩形的宽度和高度
    width = x1 - x0
    height = y1 - y0

    # 绘制上边框
    upBMP = win32gui.CreateCompatibleBitmap(dc, width, size)
    win32gui.SelectObject(cdc, upBMP)
    win32gui.FillRect(cdc, (0, 0, width, size), brush)
    win32gui.BitBlt(dc, x0, y0, width, size, cdc, 0, 0, win32con.SRCCOPY)

    # 绘制下边框
    downBMP = win32gui.CreateCompatibleBitmap(dc, width, size)
    win32gui.SelectObject(cdc, downBMP)
    win32gui.FillRect(cdc, (0, 0, width, size), brush)
    win32gui.BitBlt(dc, x0, y1 - size, width, size, cdc, 0, 0, win32con.SRCCOPY)

    # 绘制左边框
    leftBMP = win32gui.CreateCompatibleBitmap(dc, size, height)
    win32gui.SelectObject(cdc, leftBMP)
    win32gui.FillRect(cdc, (0, 0, size, height), brush)
    win32gui.BitBlt(dc, x0, y0, size, height, cdc, 0, 0, win32con.SRCCOPY)

    # 绘制右边框
    rightBMP = win32gui.CreateCompatibleBitmap(dc, size, height)
    win32gui.SelectObject(cdc, rightBMP)
    win32gui.FillRect(cdc, (0, 0, size, height), brush)
    win32gui.BitBlt(dc, x1 - size, y0, size, height, cdc, 0, 0, win32con.SRCCOPY)


def draw_text_by_position(dc, cdc, x0, y0, x1, y1, size, text, font_size=24):
    # 如果提供了文本，则在矩形下方绘制文本
    if text:
        text = text.strip()
        lines = text.split('\n')

        # 计算矩形的宽度和高度
        width = x1 - x0
        height = y1 - y0
        import win32api
        import win32ui
        # import win32gui

        # 设置文本颜色（这里使用黑色，可以根据需要修改）
        text_color = win32api.RGB(0, 0, 0)
        win32gui.SetTextColor(dc, text_color)

        # 创建更大的字体（这里设置为 24 号字）
        # font_height = -24  # 负值表示以点为单位

        font_size = min(width - 12, font_size)
        if font_size <= 12:
            return
        # font_size = width - 12

        # 创建字体属性字典
        font_attributes = {
            "height": -font_size,  # 字体高度（负值表示以点为单位）
            "width": 0,  # 字体宽度（0表示自动计算）
            "escapement": 0,  # 文本倾斜角度
            "orientation": 0,  # 文本旋转角度
            "weight": win32con.FW_NORMAL,  # 字体粗细
            "italic": 0,  # 0=不斜体，1=斜体
            "underline": 0,  # 0=无下划线，1=有下划线
            # "strikeOut": 0,  # 0=无删除线，1=有删除线
            # "charset": win32con.DEFAULT_CHARSET,
            # "outPrecision": win32con.OUT_DEFAULT_PRECIS,
            # "clipPrecision": win32con.CLIP_DEFAULT_PRECIS,
            # "quality": win32con.DEFAULT_QUALITY,
            # "pitchAndFamily": win32con.DEFAULT_PITCH | win32con.FF_DONTCARE,
        }

        # 使用字典创建字体
        font = win32ui.CreateFont(font_attributes)
        # 设置文本背景模式为透明
        # win32gui.SetBkMode(dc, win32con.TRANSPARENT)
        dc_obj = win32ui.CreateDCFromHandle(dc)
        dc_obj.SelectObject(font)

        # 获取文本高度
        # cdc_obj = win32ui.FromHandle(CDC)
        # text_metrics = cdc_obj.GetTextMetrics()
        # line_height = text_metrics['tmHeight'] + 5  # 行高 + 间距

        # 计算文本位置（矩形下方居中）
        text_x = x0 + (width // 2)  # 水平居中
        # text_y = y0 + size + 5  # 矩形底部下方留出一些间距

        # 获取文本尺寸
        text_width, text_height = win32gui.GetTextExtentPoint32(dc, text)


        # 绘制文本
        # win32gui.ExtTextOut(dc, text_x, text_y, text)

        # 绘制文本（修复参数错误，正确传递7个参数）
        # ExtTextOut的正确参数：dc, x, y, 选项,Z 矩形区域, 文本, 字符间距
        if len(lines) <= 1:
            text_y = y1 + size + 5  # 矩形底部下方留出一些间距

            text_x -= text_width // 2
            win32gui.ExtTextOut(dc, text_x, text_y, 0, None, text, None)
        else:
            text_y = y1 + size - 5  # 矩形底部下方留出一些间距

            line_height = font_size + 5

            # 调整x坐标使文本完全居中
            # text_x = text_x - text_width // len(lines) + font_size
            # text_x = min(text_x, x0)
            text_x = x0 + 10
            # 绘制起始位置
            x, y = text_x, text_y

            # 逐行绘制
            for i, line in enumerate(lines):
                current_y = y + i * line_height
                win32gui.ExtTextOut(dc, x, current_y, 0, None, line, None)


def get_center_for_rect(rect):
    x0, y0, x1, y1 = rect
    return (x0 + x1) // 2, (y0 + y1) // 2


def get_distance_for_2_rect(rect_0, rect_1):
    center_0 = get_center_for_rect(rect_0)
    center_1 = get_center_for_rect(rect_1)
    distance = math.sqrt(math.pow(center_1[0] - center_0[0], 2) + math.pow(center_1[1] - center_0[1], 2))
    return round(distance, 3)


if __name__ == '__main__':
    rect_0 = (0, 0, 10, 10)
    rect_1 = (1, 1, 11, 11)
    distance = get_distance_for_2_rect(rect_0, rect_1)
    print(f'--- distance: {distance}')


